package ae.pcfc.cldos.online.common.facade.provider;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.transaction.annotation.Transactional;

import ae.pcfc.cldos.online.common.ConstantsCommon;
import ae.pcfc.cldos.online.common.ConstantsCommon.Steps;
import ae.pcfc.cldos.online.common.UltimusConstants;
import ae.pcfc.cldos.online.common.UltimusConstants.ApplicationResubmitDecision;
import ae.pcfc.cldos.online.common.UltimusConstants.EmployeeType;
import ae.pcfc.cldos.online.common.clddb.domain.AppMetaData;
import ae.pcfc.cldos.online.common.clddb.domain.ApplicationStatus;
import ae.pcfc.cldos.online.common.clddb.domain.AttachmentType;
import ae.pcfc.cldos.online.common.clddb.domain.Process;
import ae.pcfc.cldos.online.common.clddb.domain.ReviewComments;
import ae.pcfc.cldos.online.common.clddb.domain.ServiceMaster;
import ae.pcfc.cldos.online.common.clddb.domain.TaskMaster;
import ae.pcfc.cldos.online.common.clddb.domain.TempFileStorage;
import ae.pcfc.cldos.online.common.clddb.domain.VisitVisaCancel;
import ae.pcfc.cldos.online.common.clddb.domain.manager.VisitVisaCancelDOM;
import ae.pcfc.cldos.online.common.etksdb.domain.User;
import ae.pcfc.cldos.online.common.exception.BadAppException;
import ae.pcfc.cldos.online.common.exception.InvalidEmpIdException;
import ae.pcfc.cldos.online.common.exception.UltimusAppException;
import ae.pcfc.cldos.online.common.facade.BaseProcesesFacade;
import ae.pcfc.cldos.online.common.facade.VisitVisaCancelFacade;
import ae.pcfc.cldos.online.common.factories.AppMetaDataFactory;
import ae.pcfc.cldos.online.common.vo.AppSaveResponseVO;
import ae.pcfc.cldos.online.common.vo.FileVO;
import ae.pcfc.cldos.online.common.vo.UserVO;
import ae.pcfc.cldos.online.common.vo.fnp.FNPPaymentAdviceVO;
import ae.pcfc.cldos.online.common.vo.vv.cancel.VisitVisaCancelDetailsVO;
import ae.pcfc.cldos.online.common.vo.vv.cancel.VisitVisaCancelVO;
import ae.pcfc.cldos.online.gs.ConstantsGS;
import ae.pcfc.cldos.online.gs.service.client.vo.NotificationVO;
import ae.pcfc.cldos.online.wf.ConstantsWF;
import ae.pcfc.cldos.online.wf.service.client.vo.appdata.VisitVisaCancelAppInfo;
import ae.pcfc.cldos.online.wf.service.client.vo.base.BaseResubmitGVariablesVO;
import ae.pcfc.cldos.online.wf.service.client.vo.base.BaseSubmitGVariablesVO;
import ae.pcfc.cldos.online.wf.service.client.vo.base.CompleteStepVO;
import ae.pcfc.cldos.online.wf.service.client.vo.base.LaunchIncedentVO;

/**
 * 
 * @author arosa
 *
 */
public class VisitVisaCancelFacadeImpl extends BaseProcesesFacade implements VisitVisaCancelFacade {

	
	private VisitVisaCancelDOM visitVisaCancelDOM;
	
	public void setVisitVisaCancelDOM(VisitVisaCancelDOM visitVisaCancelDOM) {
		this.visitVisaCancelDOM = visitVisaCancelDOM;
	}
	
	@Transactional
	public VisitVisaCancelVO getEmploymentVisaCancelationAppInfo(String appId, UserVO userVO, Steps step) throws BadAppException{
		
		VisitVisaCancelVO visitVisaCancelVO = new VisitVisaCancelVO();
		AppMetaData appMetaData = null;
		
		if(userVO.isGeneralAdmin()){
			appMetaData = appMetaDataDOM
				.getAppMetaDataByIdForGeneralAdmin(appId, Process.PROCESS_CANCEL_VISIT_VISA, step);
		} else {
			User user = userDomainObjectManager.findUserByUserName(userVO.getUsername());
			appMetaData = appMetaDataDOM
					.getAppMetaDataById(appId, Process.PROCESS_CANCEL_VISIT_VISA, step, user.getClientId());
		}
		VisitVisaCancelDetailsVO visitVisaCancelDetailsVO = new VisitVisaCancelDetailsVO();
		getMapper().map(appMetaData.getVisitVisaCancel(), visitVisaCancelDetailsVO);
		visitVisaCancelVO.setVisaCancelDetailsVO(visitVisaCancelDetailsVO);
		
		visitVisaCancelVO.setClientReferenceNo(appMetaData.getClientRefNo());
		visitVisaCancelVO.setInitiatedBy(appMetaData.getWfInitiatedBy());
		
		List<TempFileStorage> tempFileStoragesList = appMetaData.getTempFileStorages();
		List<FileVO> fileVOList = new ArrayList<FileVO>(tempFileStoragesList.size());
		for(TempFileStorage tempFileStorage : tempFileStoragesList){
			FileVO fileVO = new FileVO();
			getMapper().map(tempFileStorage, fileVO);
			if(fileVO.getAttachmentTypeCode().equals(AttachmentType.__ATTACHMENT_TYPE_EXIT_DOCUMENT)){
				visitVisaCancelVO.setExitDocument(fileVO);
			} else { 
				fileVOList.add(fileVO);
			}
		}
		visitVisaCancelVO.setFileVOList(fileVOList);
		visitVisaCancelVO.setApplicationCommentVOs(getCommentsVOList(appMetaData.getReviewComments()));
		try{
			visitVisaCancelVO.setWfStatus(gsInfoManager.getWfStatus(visitVisaCancelVO.getClientReferenceNo()));
		}catch(Exception e){
			visitVisaCancelVO.setWfStatus(ConstantsGS.EMP_STATUS_NA);
		}
		return visitVisaCancelVO;
	}
	
	@Transactional(rollbackFor=Exception.class)
	public AppSaveResponseVO submit(VisitVisaCancelVO visitVisaCancelVO) throws Exception{
		return storeToDb(visitVisaCancelVO, null, false);
	}
	
	@Transactional(rollbackFor=Exception.class)
	public AppSaveResponseVO reSubmit(VisitVisaCancelVO visitVisaCancelVO, String appId) throws Exception{
		return storeToDb(visitVisaCancelVO, appId, true);
	}
	
	private AppSaveResponseVO storeToDb(VisitVisaCancelVO visitVisaCancelVO, String appId, boolean isResubmit) throws Exception{
		AppSaveResponseVO appSaveResponseVO = new AppSaveResponseVO();
		Integer incident = null; 
		
		UserVO userVO =  visitVisaCancelVO.getUserVO();
		User user = userDomainObjectManager.findUserByUserName(userVO.getUsername());
		
		String compLicNo = tTscClientCompanyDOM.getLicenseNumberNyTrakheesId(user.getClient().getCTrakheesId());
		if(userVO.isAdmin()){
			gsInfoManager.isRequestExist(Process.PROCESS_CANCEL_VISIT_VISA,null, visitVisaCancelVO.getVisaCancelDetailsVO().getVvcEmployeeId());
			if(!gsEmployeeDetailsManager.validateVisitor(visitVisaCancelVO.getVisaCancelDetailsVO().getVvcEmployeeId(), 
					compLicNo)){
				throw new InvalidEmpIdException();
			}
		}
		AppMetaDataFactory appMetaDataFactory = null;
		String clientRefNo = null;
		boolean backOfficeRejectflag=false;
		if(isResubmit){
			AppMetaData appMetaData = appMetaDataDOM.getAppMetaDataById(appId, 
					Process.PROCESS_CANCEL_VISIT_VISA, Steps.RESUBMIT, user.getClientId());
			appMetaDataFactory = AppMetaDataFactory.createReSubmitFactory(appMetaData);
			if(appMetaData.getStatusCode()==5){
				backOfficeRejectflag=true;
			}
			if(userVO.isAdmin() && !backOfficeRejectflag){
				clientRefNo = gsInfoManager.getNextOfflineAppId(Process.PROCESS_CANCEL_VISIT_VISA);
				appMetaData.setClientRefNo(clientRefNo);
			}
			
		} else {
			if(userVO.isAdmin()){
				clientRefNo = gsInfoManager.getNextOfflineAppId(Process.PROCESS_CANCEL_VISIT_VISA);
			}
			appMetaDataFactory = AppMetaDataFactory.createSubmitFactory(clientRefNo);
		}
		
		AppMetaData appMetaData = appMetaDataFactory.getAppMetaData();
		
		appMetaData.setServiceCode(ServiceMaster.CANCEL_VV);
		
		if(userVO.isAdmin()){
			appMetaData.setStatusCode(ApplicationStatus.STATUS_APPROVED_BY_ONLINE_ADMIN);
		}else if (!isResubmit) {
			appMetaData.setStatusCode(ApplicationStatus.STATUS_INITIATED);
		} else {
			appMetaData.setStatusCode(ApplicationStatus.STATUS_RESUBMITED);
		}
		
		appMetaData.setProcessCode(Process.PROCESS_CANCEL_VISIT_VISA);
		appMetaData.setUserId(user.getUId());
		appMetaData.setClientId(user.getClientId());
		appMetaData.setApplicationDate(new Date());
		if(!isResubmit || appMetaData.getApplicationId()==null){
			appMetaDataDOM.add(appMetaData);
		}
		
		
		if(isResubmit){
			taskAndNotificationsManager.completeAllByAppId(appMetaData.getApplicationId());
		}
		
		if(!userVO.isAdmin()){	
			taskAndNotificationsManager.sendTask(appMetaData, TaskMaster.__ADMIN_APPROVE_TASK_CODE);
		}
		
		VisitVisaCancel visitVisaCancel = appMetaDataFactory.getVisitVisaCancel();
		getMapper().map(visitVisaCancelVO.getVisaCancelDetailsVO(), visitVisaCancel);
		visitVisaCancel.setAppMetaData(appMetaData);
		visitVisaCancelDOM.add(visitVisaCancel);
		appMetaData.setVisitVisaCancel(visitVisaCancel);
		
		String referenceNumber = appMetaData.getApplicationId().toString();
		if(!userVO.isAdmin() && !backOfficeRejectflag){
			appMetaData.setClientRefNo(referenceNumber);
		}
		
		appMetaData.setTempFileStorages(fileStorageManager.storeFiles(appMetaData, visitVisaCancelVO.getFileVOList(), 
				appMetaDataFactory.getTempFileStoragesMap()));
		
		//add list of param here
		if(userVO.isAdmin() && visitVisaCancelVO.getFnpServiceCode()!=null && !visitVisaCancelVO.getFnpServiceCode().isEmpty()){
			 String fnpServiceCode = visitVisaCancelVO.getFnpServiceCode();
			 FNPPaymentAdviceVO fnpPaymentAdviceVO = 
					 fnpManager.generatePayment(appMetaData.getApplicationId(), userVO.getUsername(), fnpServiceCode, 
							 visitVisaCancelVO.getFnpParams(),null,appMetaData.getClientRefNo());
			 appMetaData.setPaymentAdviceNo(fnpPaymentAdviceVO.getPaymentAdviceNumber());
			 appMetaData.getTempFileStorages().add(fnpPaymentAdviceVO.getStoredPaymentAdvice());
		}if(visitVisaCancelVO.getFnpServiceCode()==null || visitVisaCancelVO.getFnpServiceCode().isEmpty()){
			appMetaData.setPaymentAdviceNo(null);
		}
		
		VisitVisaCancelAppInfo visitVisaCancelAppInfo = new VisitVisaCancelAppInfo();
		getMapper().map(visitVisaCancelVO.getVisaCancelDetailsVO(), visitVisaCancelAppInfo);
		visitVisaCancelAppInfo.setG_ApplicationDate(appMetaData.getApplicationDate());
		
		/*add action comment*/
		ReviewComments reviewComments = new ReviewComments();
		reviewComments.setApplicationId(appMetaData.getApplicationId());
		reviewComments.setStatusCode(appMetaData.getStatusCode());
		reviewComments.setRcUserName(user.getUUsername());
		reviewComments.setRcComments(visitVisaCancelVO.getComment());
		reviewCommentsDOM.add(reviewComments);
		
		/*Send notification*/
		//if(!userVO.isAdmin()){
			NotificationVO notificationVO = new NotificationVO();
			notificationVO.setOnlineAppId(appMetaData.getApplicationId().toString());
			Map<Object, Object> parameters = new HashMap<Object, Object>();
			parameters.put("comments", visitVisaCancelVO.getComment());
			notificationVO.setParameters(parameters);
			taskAndNotificationsManager.sendNotification(appMetaData, notificationVO);
		//}
		
		//launch workflow
		if(appMetaData.getWfIncidentId() == null){
			if(userVO.isAdmin()){
				LaunchIncedentVO launchIncedentVO = new LaunchIncedentVO();
				BaseSubmitGVariablesVO baseSubmitGVariablesVO = new BaseSubmitGVariablesVO();
				baseSubmitGVariablesVO.setG_ApplicationID(referenceNumber);
				baseSubmitGVariablesVO.setG_ApplicationSubmissionMedium(ConstantsCommon.APPLICATION_SUBMISSION_MEDIUM_ONLINE);
				baseSubmitGVariablesVO.setG_ApplicationLaunchedBy(EmployeeType.COMPANY_ADMIN.getEmployeeType());
				try{		
					incident = genericVisaWF.launchIncident(appMetaData.getProcessCode(), launchIncedentVO, 
							baseSubmitGVariablesVO, visitVisaCancelAppInfo);
				}catch (Exception e) {
					e.printStackTrace();
					if(appMetaData.getPaymentAdviceNo() !=null){
						fnpManager.cancelPayment(appMetaData.getApplicationId().toString(), userVO.getUsername(), appMetaData.getPaymentAdviceNo(),appMetaData.getClientRefNo());
					}
					throw new UltimusAppException(e);
				}
				appMetaData.setWfIncidentId(incident.toString());
				appMetaData.setWfInitiatedBy(user.getUUsername());
			}
		} else{
			 incident = Integer.parseInt(appMetaData.getWfIncidentId());
			CompleteStepVO completeStepVO = new CompleteStepVO();
			completeStepVO.setStrStepName(UltimusConstants.RESUBMIT_ONLINE_APPLICATION_STEP);
			completeStepVO.setStrUserName(ConstantsWF.ULTIMUS_ANONYMOUS_USER);
			completeStepVO.setnIncidentNumber(incident);
			
			
			//:TODO put code for WF inwocation for resubmit
			BaseResubmitGVariablesVO baseResubmitGVariablesVO = new BaseResubmitGVariablesVO();
			baseResubmitGVariablesVO.setG_ApplicationID(referenceNumber);
			
			if(!userVO.isAdmin()){
				baseResubmitGVariablesVO.setG_ApplicationResubmittedBy(EmployeeType.EMPLOYEE.getEmployeeType());
			}else{
				baseResubmitGVariablesVO.setG_ApplicationResubmittedBy(EmployeeType.COMPANY_ADMIN.getEmployeeType());
			}
			baseResubmitGVariablesVO.setG_ApplicationResubmitDecision(ApplicationResubmitDecision.RESUBMITTED.getResubmitDecision());
			
			try{		
				genericVisaWF.completeStep(appMetaData.getProcessCode(), completeStepVO, baseResubmitGVariablesVO, 
						visitVisaCancelAppInfo);
			}catch (Exception e) {
				e.printStackTrace();
				if(userVO.isAdmin() && appMetaData.getPaymentAdviceNo() !=null){
					fnpManager.cancelPayment(appMetaData.getApplicationId().toString(), userVO.getUsername(), appMetaData.getPaymentAdviceNo(),appMetaData.getClientRefNo());
				}
				throw new Exception(e);
			}
		}
		
		/*
		 * transfer request to GS
		 */
			transferDataToGS(appMetaData, userVO, compLicNo);
		/*
		 * end of transfer
		 */
		
		if(isResubmit){
			appMetaDataDOM.update(appMetaData);
		} else {
			appMetaDataDOM.updateAndAddEtks(appMetaData);
		}
		
		appSaveResponseVO.setReferenceNo(appMetaData.getClientRefNo());
		appSaveResponseVO.setIncidentNo(appMetaData.getWfIncidentId());
		return appSaveResponseVO;
	}
}
